home *** CD-ROM | disk | FTP | other *** search
/ Freaks Macintosh Archive / Freaks Macintosh Archive.bin / Freaks Macintosh Archives / Ham⁄GPS / SoftKiss.src.1.8 Folder / SoftKiss.src.1.8 / core / sfk_core_interupt.c < prev    next >
Text File  |  1993-03-13  |  17KB  |  709 lines

  1. /*
  2.  * SoftKiss device handling code interupt handling code
  3.  * by Aaron Wohl / N3LIW (aw0g+@andrew.cmu.edu) jul 1990
  4.  * 6393 Penn Ave #303
  5.  * Pittsburgh PA, 15206
  6.  * work: (412)-268-5032
  7.  * home: (412)-731-6159
  8.  */
  9.  
  10. #include "sfk_core.h"
  11. #include "sfk_core_private.h"
  12. #include "asm.h"
  13. #include "8530.h"
  14.  
  15. /*
  16.  * option a45_globals is set by the thinkc compiler when
  17.  * making a driver or code resource
  18.  */
  19. #if __option(a4_globals)
  20. #define sfk_GLOBAL_REG a4
  21. #else
  22. #define sfk_GLOBAL_REG a5
  23. #endif
  24.  
  25. #define MAGIC_UNPATCHED_NUMBER 0x12345678
  26.  
  27. #ifdef CODECHECK                //codecheck doesn't know about asm constructs
  28. #define sfk_SETUP_GLOBAL_REG    //fake macro for codecheck
  29. #define sfk_RESTORE_GLOBAL_REG    //fake macro for codecheck
  30. #else
  31. #define sfk_SETUP_GLOBAL_REG \
  32.     asm { jsr sfk_find_address } \
  33.     asm { move.l sfk_GLOBAL_REG,-(a7) } \
  34.     asm { move.l #MAGIC_UNPATCHED_NUMBER,sfk_GLOBAL_REG } /*patch at runtime*/
  35.  
  36. #define sfk_RESTORE_GLOBAL_REG \
  37.     asm { move.l (a7)+,sfk_GLOBAL_REG }
  38. #endif
  39.  
  40. /*system interupt vectors*/
  41. #define sfk_Lvl2_B_transm 0        /*Lvl2DT index for SCC B transmit interupt*/
  42. #define sfk_Lvl2_B_data 2        /*Lvl2DT index for SCC B data interupt*/
  43. #define sfk_Lvl2_B_special 3    /*Lvl2DT index for SCC B special interupt*/
  44. #define sfk_Ext_B 0                /*ExtStsDT index for SCC B external*/
  45.  
  46. #define sfk_Lvl2_A_transm 4        /*Lvl2DT index for SCC A transmit interupt*/
  47. #define sfk_Lvl2_A_data 6        /*Lvl2DT index for SCC A data interupt*/
  48. #define sfk_Lvl2_A_special 7    /*Lvl2DT index for SCC A special interupt*/
  49. #define sfk_Ext_A 2                /*ExtStsDT index for SCC A external*/
  50.  
  51. /*
  52.  * helper routine to help locate where code is actually
  53.  * located.  when you take the address of code with a & you
  54.  * get the jump table address
  55.  * returns to callers caller with result in a0
  56.  */
  57. static void sfk_find_address()
  58. {
  59. #ifndef CODECHECK
  60.     asm { move.l (a7)+,a0 }
  61. #endif
  62. }
  63.  
  64. /*
  65.  * begin actually transmiting data
  66.  * -interupt
  67.  */
  68. static void sfk_xmit_first_byte(sfk_prt_pt p)
  69. {
  70.     sfk_go_state(p,PX_XMIT);
  71. }
  72.  
  73. /*
  74.  * clear an overrun condition
  75.  */
  76. static void sfk_recv_overrun(sfk_prt_pt p)
  77. {
  78.     p->sfk_IVAR(recv_overrun)++;
  79.      sfk_write_scc(p,R3,Rx8|ENT_HM|RxCRC_ENAB|SYNC_L_INH|RxENABLE); /*enter hunt mode*/
  80.      /*bug, deal with partial packet*/
  81. }
  82.  
  83. /*
  84.  * end of current input packet
  85.  */
  86. static void sfk_end_of_rx_packet(sfk_prt_pt p,int isgood)
  87. {
  88.   register long pak_len=p->in_count;
  89.   if(pak_len > p->sfk_IVAR(recv_largest_seen))
  90.        p->sfk_IVAR(recv_largest_seen)=pak_len;
  91.   if((pak_len > p->sfk_IVAR(max_packet_size))||
  92.         (pak_len < (SFK_MIN_PACK_SIZE+1)))
  93.           isgood=FALSE;        /*too short*/
  94.   p->sfk_in->cnt=pak_len-1;    /*don't count the one FCS byte buffered*/
  95.   if(isgood&&(p->sfk_freehq.sfk_size>0)&&(p->sfk_freedq.sfk_size>0)) { /*can't use last packet*/
  96.     sfk_enqueue(&p->sfk_recvq,p->sfk_in);
  97.      p->sfk_in=0;
  98.   }
  99.   sfk_prep_rx(p);
  100.   sfk_go_state(p,PX_RX);
  101. }
  102.  
  103. /*
  104.  * prepare the sfk_in packet to be ready to start recieving
  105.  */
  106. void sfk_prep_rx(sfk_prt_pt p)
  107. {
  108.   register sfk_packet_pt ap=p->sfk_in;
  109.   if(ap==0)
  110.     SFK_ASSERT(((ap=sfk_allocate_packet(p))!=0),SFK_TEXT(61));
  111.   p->in_count=0;
  112.   p->sfk_in=ap;
  113.   ap->cnt=0;
  114.   ap->att_read=0;
  115.   ap->data_flags=0;
  116. }
  117.  
  118. /*
  119.  * handle data arrived interupt but no more buffer space
  120.  */
  121. static void sfk_recv_chuck_data_int(sfk_prt_pt p)
  122. {
  123.      sfk_write_scc(p,R3,Rx8|ENT_HM|RxCRC_ENAB|SYNC_L_INH|RxENABLE); /*enter hunt mode*/
  124.     while((sfk_read_scc(p,R0)&Rx_CH_AV)!=0)
  125.         sfk_read_scc_data(p);
  126. }
  127.  
  128. /*
  129.  * handle special interupt
  130.  */
  131. static void sfk_special_int(sfk_prt_pt p)
  132. {
  133.   int status;
  134.   status=sfk_read_scc(p,R1);
  135.   sfk_write_scc(p,R0,ERR_RES);        /*reset rx and error*/
  136.   if(status&Rx_OVR)
  137.     sfk_recv_overrun(p);
  138.   sfk_recv_chuck_data_int(p);
  139.   sfk_end_of_rx_packet(p,
  140.         ((status&(CRC_ERR|Rx_OVR|RES18))==RES8));        /*good if no overrun or bad crc or bad residue*/
  141.   if(WANT_XMIT(p))
  142.       sfk_initiate_xmit(p);
  143. }
  144.  
  145. /*
  146.  * force keydown
  147.  */
  148. void sfk_keydown(sfk_prt_pt p)
  149. {
  150.   /*save time by not clearing timer now, if it wakes up it will
  151.     not do anything if xmit abort is set*/
  152.   // sfk_clear_timer(p);
  153.   p->timer_ignore=TRUE;
  154.   sfk_write_scc(p,R5,
  155.           (p->scc_reg_cache[R5]&
  156.               (~(DTR|TxENAB|RTS|TxCRC_ENAB)))|
  157.               p->extra_tx_bits_for_line_power);
  158.  
  159. }
  160.  
  161. /*
  162.  * clear the timer if it is set
  163.  */
  164. void sfk_clear_timer(sfk_prt_pt p)
  165. {
  166.   if(p->timer_installed)
  167.     RmvTime((QElemPtr)&p->timer_task);
  168.   p->timer_installed=FALSE;
  169. }
  170.  
  171. /*
  172.  * set the timer to call to the specified routine after delay
  173.  * delay is in milliseconds if posative or microseconds if negative
  174.  */
  175. void sfk_install_timer(sfk_prt_pt p,void (*rtn)(sfk_prt_pt p),long delay)
  176. {
  177.   // sfk_clear_timer(p);
  178.   p->timer_ignore=TRUE;
  179.   if(!p->timer_installed) {
  180.       p->timer_installed=TRUE;
  181.       memset(&p->timer_task,0,sizeof(p->timer_task));
  182.       p->timer_task.tmAddr= (ProcPtr)(p->low_level_timer_routine);
  183.       InsTime((QElemPtr)&p->timer_task);
  184.   }
  185.   p->timer_routine=rtn;
  186.   p->timer_ignore=FALSE;
  187.   PrimeTime((QElemPtr)&p->timer_task,delay);
  188. }
  189.  
  190. /*
  191.  * handler for an unexpected xmit interupt
  192.  * shouldn't happen, only listed possible cause in manual
  193.  * is xmit underflow
  194.  * an abort is automaticly transmited by the sc
  195.  */
  196. static void sfk_unexpected_xmit_int(sfk_prt_pt p)
  197. {
  198.     p->sfk_IVAR(xmit_overrun)++;
  199.     sfk_go_state(p,PX_TAIL);
  200. }
  201.  
  202. /*
  203.  * got an xmit interupt when we don't need one
  204.  */
  205. static void sfk_end_xmit(sfk_prt_pt p)
  206. {
  207.     sfk_write_scc(p,R0,RES_Tx_P);
  208. }
  209.  
  210. /*
  211.  * put scc in xmit mode and schedule transmit
  212.  */
  213. void sfk_tell_scc_to_xmit(sfk_prt_pt p)
  214. {
  215.     sfk_scc_set_buad_divider_xmit(p);
  216.     sfk_cand_scc(p,R15,TxUIE);
  217.     sfk_or_scc(p,R5,DTR|TxENAB|RTS|TxCRC_ENAB);        /*turn on DTR for xmit*/
  218.     sfk_keyup(p,p->sfk_IVAR(os_tx_delay));
  219. }
  220.  
  221. /*
  222.  * ignore an interupt
  223.  */
  224. static void sfk_ignore_int(sfk_prt_pt p)
  225. {
  226. }
  227.  
  228. /*
  229.  * keyup and schedule transmit
  230.  */
  231. void sfk_keyup(sfk_prt_pt p,long delay_time)
  232. {
  233.     p->pr_recv_int=sfk_recv_chuck_data_int;
  234.     p->pr_spcl_int=sfk_ignore_int;
  235.     p->pr_extr_int=sfk_ignore_int;
  236.     sfk_install_timer(p,sfk_xmit_first_byte,delay_time);
  237. }
  238.  
  239. /*
  240.  * call timer routine for port b
  241.  */
  242. static void timer_handler_b()
  243. {
  244.     sfk_SETUP_GLOBAL_REG;
  245.     sfk_SCC_interupts_off;
  246.     if(!sfk_PB->timer_ignore)
  247.         (*sfk_PB->timer_routine)(sfk_PB);
  248.     sfk_SCC_interupts_on;
  249.     sfk_RESTORE_GLOBAL_REG;
  250. }
  251.  
  252. /*
  253.  * call timer routine for port a
  254.  */
  255. static void timer_handler_a()
  256. {
  257.     sfk_SETUP_GLOBAL_REG;
  258.     sfk_SCC_interupts_off;
  259.     if(!sfk_PA->timer_ignore)
  260.         (*sfk_PA->timer_routine)(sfk_PA);
  261.     sfk_SCC_interupts_on;
  262.     sfk_RESTORE_GLOBAL_REG;
  263. }
  264.  
  265. /*
  266.  * begin transmiting
  267.  * call with interupts off
  268.  */
  269. void sfk_initiate_xmit(sfk_prt_pt p)
  270. {
  271.     if(p->sfk_state!=PX_RX)
  272.         return;
  273.     if(!WANT_XMIT(p))
  274.         return;
  275.     sfk_go_state(p,PX_SLOT_WAIT);
  276. }
  277.  
  278. /*
  279.  * handle external/status interupt
  280.  */
  281. static void sfk_recv_external_int(sfk_prt_pt p)
  282. {
  283.   sfk_end_of_rx_packet(p,FALSE);
  284. }
  285.  
  286. /*
  287.  * handle data arrived interupt in recive mode
  288.  */
  289. static void sfk_recv_data_read_int(sfk_prt_pt p)
  290. {
  291.       register sfk_packet_pt ap=p->sfk_in;
  292.     uint8 abyte;
  293.     while((sfk_read_scc(p,R0)&Rx_CH_AV)!=0) {
  294.         char ch=sfk_read_scc_data(p);
  295.         *(ap->data+p->in_count++)=ch;
  296.         dbo_fputc(&p->dbo,ch);
  297.         // dbo_fputc(&p->dbo,'R');
  298.         if(p->in_count >= p->sfk_IVAR(max_packet_size)) {
  299.             ap->data_flags|=sfk_db_LONG;
  300.             sfk_go_state(p,PX_RX_CHUCK);
  301.             return;
  302.         }
  303.     }
  304. }
  305.  
  306. /*
  307.  * transition to actually recieving a packet
  308.  */
  309. void sfk_set_recv_now_mode(sfk_prt_pt p)
  310. {
  311.     register sfk_packet_pt ap=p->sfk_in;
  312.     ap->sfk_time_in=Ticks;
  313.     p->pr_recv_int=sfk_recv_data_read_int;
  314.      sfk_recv_data_read_int(p);
  315. }
  316.  
  317. /*
  318.  * transition to actually recieve packet but throw away data
  319.  */
  320. void sfk_set_recv_chuck_mode(sfk_prt_pt p)
  321. {
  322.     p->pr_recv_int=sfk_recv_chuck_data_int;
  323.     sfk_recv_chuck_data_int(p);
  324. }
  325.  
  326. /*
  327.  * send bytes interupt
  328.  */
  329. static void sfk_xmit_int(sfk_prt_pt p)
  330. {
  331.       register sfk_packet_pt ap=p->sfk_out;
  332.       if(p->sfk_state!=PX_XMIT) {
  333.         sfk_end_xmit(p);
  334.         return;
  335.       }
  336.     while((sfk_read_scc(p,R0)&Tx_BUF_EMP)!=0) {
  337.         char ch=*(ap->data+p->out_count++);
  338.         sfk_write_scc_data(p,ch);
  339.         dbo_fputc(&p->dbo,ch);
  340.         // dbo_fputc(&p->dbo,'S');
  341.         if(p->out_count >= ap->cnt) {
  342.             sfk_cand_scc(p,R10,ABUNDER);    //let crc and flag go out
  343.             sfk_go_state(p,PX_TAIL);
  344.             return;
  345.         }
  346.     }
  347. }
  348.  
  349. /*
  350.  * set state to allow crc/sync char to go out
  351.  */
  352. void sfk_tail(sfk_prt_pt p)
  353. {
  354.     sfk_end_xmit(p);
  355.     sfk_cand_scc(p,R15,TxUIE);
  356.     sfk_cand_scc(p,R1,TxINT_ENAB);    //no xmit interupt
  357.     if(p->sfk_out!=0)
  358.          sfk_free_packet(p,p->sfk_out);
  359.     p->sfk_out=0;
  360.     sfk_keyup(p,p->sfk_IVAR(os_tail_delay));
  361. }
  362.  
  363. /*
  364.  * start transmiting
  365.  */
  366. void sfk_send_first_byte(sfk_prt_pt p)
  367. {
  368.     register sfk_packet_pt ap;
  369.     if((ap=sfk_dequeue(&p->sfk_xmitq))==0) {
  370.         sfk_go_state(p,PX_RX);            //strange should have had a packet
  371.         return;
  372.     }
  373.     p->pr_extr_int=sfk_unexpected_xmit_int;
  374.     p->sfk_out=ap;
  375.     p->out_count=0;
  376.     sfk_or_scc(p,R10,ABUNDER);            //enable underrun protection
  377.     sfk_write_scc(p,R0,RES_Tx_CRC);        //reset tx crc
  378.     sfk_xmit_int(p);
  379.     if(p->sfk_state==PX_XMIT) {
  380.         // must be reset after first and before last byte
  381.         // see z85c30 amd serial communications control technical manual
  382.         // page 4-21
  383.         sfk_write_scc(p,R0,RES_EOM_L);    //reset tx eom latch
  384.         sfk_or_scc(p,R15,TxUIE);        //interupt on underflow
  385.         sfk_or_scc(p,R1,TxINT_ENAB);    //no xmit interupt
  386.     }
  387. }
  388.  
  389. /*
  390.  * handle data arrived to start a packet
  391.  */
  392. static void sfk_recv_start_of_packet_data_int(sfk_prt_pt p)
  393. {
  394.     sfk_go_state(p,PX_RX_NOW);
  395. }
  396.  
  397. /*
  398.  * comment on external interupt
  399.  */
  400. static void ecomment(sfk_prt_pt p)
  401. {
  402.     long estatus;
  403.     asm { move.l d0,estatus }
  404.     if((estatus&BRK_ABRT)!=0)
  405.         dbo_fputc(&p->dbo,'a');
  406.     if((estatus&TxEOM)!=0)
  407.         dbo_fputc(&p->dbo,'u');
  408.     if((estatus&CTS)!=0)
  409.         dbo_fputc(&p->dbo,'c');
  410.     if((estatus&SYNC_HUNT)!=0)
  411.         dbo_fputc(&p->dbo,'h');
  412.     if((estatus&DCD)!=0)
  413.         dbo_fputc(&p->dbo,'d');
  414.     if((estatus&ZCOUNT)!=0)
  415.         dbo_fputc(&p->dbo,'z');
  416.  }
  417.  
  418. /*
  419.  * set interupts and buad rate for recieve mode
  420.  */
  421. void sfk_set_recv_mode(sfk_prt_pt p)
  422. {
  423.     sfk_scc_set_buad_divider_recv(p);
  424.     p->pr_recv_int=sfk_recv_start_of_packet_data_int;
  425.     p->pr_spcl_int=sfk_special_int;
  426.     p->pr_extr_int=sfk_recv_external_int;
  427. }
  428.  
  429. /*
  430.  * port b transmit interupt
  431.  */
  432. sfk_LDEF(void sfk_b_xmit_interupt())
  433. {
  434.     sfk_SETUP_GLOBAL_REG;
  435.       sfk_SCC_interupts_off;
  436.      sfk_PB->sfk_IVAR(xmit_interupt)++;
  437.     sfk_xmit_int(sfk_PB);
  438.     sfk_reset_scc_ius(sfk_PB);
  439.      sfk_SCC_interupts_on;
  440.     sfk_RESTORE_GLOBAL_REG;
  441. }
  442.  
  443. /*
  444.  * port b data interupt
  445.  */
  446. sfk_LDEF(void sfk_b_data_interupt())
  447. {
  448.     sfk_SETUP_GLOBAL_REG;
  449.       sfk_SCC_interupts_off;
  450.      (*sfk_PB->pr_recv_int)(sfk_PB);
  451.      sfk_PB->sfk_IVAR(data_interupt)++;
  452.      sfk_reset_scc_ius(sfk_PB);
  453.       sfk_SCC_interupts_on;
  454.     sfk_RESTORE_GLOBAL_REG;
  455. }
  456.  
  457. /*
  458.  * port b special interupt
  459.  */
  460. sfk_LDEF(void sfk_b_special_interupt())
  461. {
  462.     sfk_SETUP_GLOBAL_REG;
  463.       sfk_SCC_interupts_off;
  464.        dbo_fputc(&sfk_PB->dbo,'S');
  465.     (*sfk_PB->pr_spcl_int)(sfk_PB);
  466.      sfk_PB->sfk_IVAR(special_interupt)++;
  467.     sfk_reset_scc_ius(sfk_PB);
  468.       sfk_SCC_interupts_on;
  469.     sfk_RESTORE_GLOBAL_REG;
  470. }
  471.  
  472. /*
  473.  * port b external interupt
  474.  */
  475. sfk_LDEF(void sfk_b_external_interupt())
  476. {
  477.     sfk_SETUP_GLOBAL_REG;
  478.       sfk_SCC_interupts_off;
  479.       ecomment(sfk_PB);
  480.       dbo_fputc(&sfk_PB->dbo,'E');
  481.     (*sfk_PB->pr_extr_int)(sfk_PB);
  482.     sfk_PB->sfk_IVAR(external_interupt)++;
  483.        sfk_SCC_interupts_on;
  484.     sfk_RESTORE_GLOBAL_REG;
  485. }
  486.  
  487. /*
  488.  * port a transmit interupt
  489.  */
  490. sfk_LDEF(void sfk_a_xmit_interupt())
  491. {
  492.     sfk_SETUP_GLOBAL_REG;
  493.       sfk_SCC_interupts_off;
  494.     sfk_xmit_int(sfk_PA);
  495.     sfk_PA->sfk_IVAR(xmit_interupt)++;
  496.     sfk_reset_scc_ius(sfk_PA);
  497.       sfk_SCC_interupts_on;
  498.     sfk_RESTORE_GLOBAL_REG;
  499. }
  500.  
  501. /*
  502.  * port a data interupt
  503.  */
  504. sfk_LDEF(void sfk_a_data_interupt())
  505. {
  506.     sfk_SETUP_GLOBAL_REG;
  507.       sfk_SCC_interupts_off;
  508.      sfk_PA->sfk_IVAR(data_interupt)++;
  509.     (*sfk_PA->pr_recv_int)(sfk_PA);
  510.       sfk_reset_scc_ius(sfk_PA);
  511.       sfk_SCC_interupts_on;
  512.     sfk_RESTORE_GLOBAL_REG;
  513. }
  514.  
  515. /*
  516.  * port a special interupt
  517.  */
  518. sfk_LDEF(void sfk_a_special_interupt())
  519. {
  520.     sfk_SETUP_GLOBAL_REG;
  521.        sfk_SCC_interupts_off;
  522.        dbo_fputc(&sfk_PA->dbo,'S');
  523.     (*sfk_PA->pr_spcl_int)(sfk_PA);
  524.     sfk_PA->sfk_IVAR(special_interupt)++;
  525.      sfk_reset_scc_ius(sfk_PA);
  526.       sfk_SCC_interupts_on;
  527.     sfk_RESTORE_GLOBAL_REG;
  528. }
  529.  
  530. /*
  531.  * port a external interupt
  532.  */
  533. sfk_LDEF(void sfk_a_external_interupt())
  534. {
  535.     sfk_SETUP_GLOBAL_REG;
  536.        sfk_SCC_interupts_off;
  537.       ecomment(sfk_PA);
  538.        dbo_fputc(&sfk_PA->dbo,'E');
  539.     (*sfk_PA->pr_extr_int)(sfk_PA);
  540.       sfk_PA->sfk_IVAR(external_interupt)++;
  541.       sfk_SCC_interupts_on;
  542.     sfk_RESTORE_GLOBAL_REG;
  543. }
  544.  
  545. /*
  546.  * this table paralells the system level 2 interupt table
  547.  * it used to know which vectors to swap in
  548.  * if an entry in this table is zero then the corrisponding
  549.  * system table is not updated
  550.  */
  551. static void *sfk_lvl2_interupt_routines[8];
  552. static void *sfk_ext_interupt_routines[4];
  553.  
  554. /*offsets into level table based on port*/
  555. static int port_level_2_offset[]={sfk_Lvl2_B_transm,sfk_Lvl2_A_transm};
  556. static int ext_offset[]={sfk_Ext_B,sfk_Ext_A};
  557.  
  558. /*
  559.  * set scc level 2 interupt vectors to point to our routines
  560.  * save the old ones
  561.  * must be called with interupts off
  562.  */
  563. sfk_LDEF(void install_lvl2_interupts(sfk_prt_pt p))
  564. {
  565.     int vec_num=port_level_2_offset[p->pnum];
  566.     int num_vecs=4;
  567.     while(num_vecs-- > 0) {
  568.         if(sfk_lvl2_interupt_routines[vec_num]!=0) {
  569.             sfk_gl.saved_lvl2[vec_num]=Lvl2DT[vec_num];
  570.             Lvl2DT[vec_num]=sfk_lvl2_interupt_routines[vec_num];
  571.         }
  572.         vec_num++;
  573.     }
  574. }
  575.  
  576. /*
  577.  * must be called with interupts off
  578.  * set scc external interupt vectors to point to our routines
  579.  * save the old ones
  580.  */
  581. sfk_LDEF(void install_ext_interupts(sfk_prt_pt p))
  582. {
  583.     int vec_num=ext_offset[p->pnum];
  584.     int num_vecs=2;
  585.     while(num_vecs-- > 0) {
  586.         if(sfk_ext_interupt_routines[vec_num]!=0) {
  587.             sfk_gl.saved_ext[vec_num]=ExtStsDT[vec_num];
  588.             ExtStsDT[vec_num]=sfk_ext_interupt_routines[vec_num];
  589.         }
  590.         vec_num++;
  591.     }
  592. }
  593.  
  594. /*
  595.  * set scc interupt vectors to point to our routines
  596.  * save the old ones
  597.  * must be called with interupts off
  598.  */
  599. void sfk_install_interupt_vectors(sfk_prt_pt p)
  600. {
  601.     if(p->sfk_IVAR(our_vectors)) return;    /*if already installed no problem*/
  602.     p->sfk_IVAR(our_vectors)=TRUE;
  603.     install_lvl2_interupts(p);
  604.     install_ext_interupts(p);
  605. }
  606.  
  607. /*
  608.  * restore system level 2 interupts
  609.  * must be called with interupts off
  610.  */
  611. sfk_LDEF(void remove_lvl2_interupts(sfk_prt_pt p))
  612. {
  613.     int vec_num=port_level_2_offset[p->pnum];
  614.     int num_vecs=4;
  615.     while(num_vecs-- > 0) {
  616.         if(sfk_lvl2_interupt_routines[vec_num]!=0)
  617.             Lvl2DT[vec_num]=sfk_gl.saved_lvl2[vec_num];
  618.         vec_num++;
  619.         }
  620. }
  621.  
  622. /*
  623.  * restore system external interupts
  624.  * must be called with interupts off
  625.  */
  626. sfk_LDEF(void remove_ext_interupts(sfk_prt_pt p))
  627. {
  628.     int vec_num=ext_offset[p->pnum];
  629.     int num_vecs=2;
  630.     while(num_vecs-- > 0) {
  631.         if(sfk_ext_interupt_routines[vec_num]!=0)
  632.             ExtStsDT[vec_num]=sfk_gl.saved_ext[vec_num];
  633.         vec_num++;
  634.         }
  635. }
  636.  
  637. /*
  638.  * set scc interupt vectors to point to our routines
  639.  * save the old ones
  640.  * must be called with interupts off
  641.  */
  642. void sfk_remove_interupt_vectors(sfk_prt_pt p)
  643. {
  644.     if(!p->sfk_IVAR(our_vectors))    /*if already uninstalled no problem*/
  645.         return;
  646.     p->sfk_IVAR(our_vectors)=FALSE;
  647.     remove_lvl2_interupts(p);
  648.     remove_ext_interupts(p);
  649. }
  650.  
  651. /*
  652.  * return the contents of the global register (A5 or A4)
  653.  */
  654. static long get_global_reg()
  655. {
  656.     asm { move.l sfk_GLOBAL_REG,d0 }
  657. }
  658.  
  659. /*
  660.  * patch in global register to interupt routines
  661.  */
  662. static void patch_in_global(void *iroutine)
  663. {
  664.     long *patch_point=((long *)(((char *)iroutine)+4));
  665.     SFK_ASSERT(((*patch_point)==MAGIC_UNPATCHED_NUMBER),SFK_TEXT(62));
  666.     (*patch_point)=get_global_reg();
  667. }
  668.  
  669. /*
  670.  * initialize tables that can't be done as static initialization
  671.  * in a think code segment.  patch global register into driver routines
  672.  */
  673. static void *mk_int(void *iroutine)
  674. {
  675.     void (*rtn)(void)=iroutine;
  676.     /*call the routine to ask it where it really lives*/
  677.     (*rtn)();
  678.     asm { move.l a0,iroutine }
  679.     patch_in_global(iroutine);
  680.     return iroutine;
  681. }
  682.  
  683. /*
  684.  * patch each interupt routine to known where our data lives
  685.  */
  686. void sfk_patch_in_global_data()
  687. {
  688.   static int patched_in=FALSE;
  689.   if(patched_in)
  690.       return;
  691.   patched_in=TRUE;
  692.  
  693.   sfk_PB->low_level_timer_routine=mk_int(timer_handler_b);
  694.   
  695.   sfk_lvl2_interupt_routines[sfk_Lvl2_B_transm]=mk_int(sfk_b_xmit_interupt);
  696.   sfk_lvl2_interupt_routines[sfk_Lvl2_B_data]=mk_int(sfk_b_data_interupt);
  697.   sfk_lvl2_interupt_routines[sfk_Lvl2_B_special]=mk_int(sfk_b_special_interupt);
  698.   sfk_ext_interupt_routines[sfk_Ext_B]=mk_int(sfk_b_external_interupt);
  699.  
  700.   sfk_PA->low_level_timer_routine=mk_int(timer_handler_a);
  701.   sfk_lvl2_interupt_routines[sfk_Lvl2_A_transm]=mk_int(sfk_a_xmit_interupt);
  702.   sfk_lvl2_interupt_routines[sfk_Lvl2_A_data]=mk_int(sfk_a_data_interupt);
  703.   sfk_lvl2_interupt_routines[sfk_Lvl2_A_special]=mk_int(sfk_a_special_interupt);
  704.   sfk_ext_interupt_routines[sfk_Ext_A]=mk_int(sfk_a_external_interupt);
  705.  
  706.   sfk_some_flush();
  707. }
  708.  
  709.